package com.digua.base.util

import android.util.Log

class LogUtil {
    companion object {

        @JvmStatic
        @JvmOverloads
        fun d(data: Any?, tr: Throwable? = null) = log(data, tr) { tag, txt, tr -> tr?.let { Log.d(tag, txt, tr) } ?: Log.d(tag, txt) }

        @JvmStatic
        @JvmOverloads
        fun w(data: Any?, tr: Throwable? = null) = log(data, tr) { tag, txt, tr -> tr?.let { Log.w(tag, txt, tr) } ?: Log.w(tag, txt) }

        @JvmStatic
        @JvmOverloads
        fun e(data: Any?, tr: Throwable? = null) = log(data, tr) { tag, txt, tr -> tr?.let { Log.e(tag, txt, tr) } ?: Log.e(tag, txt) }

        @JvmStatic
        @JvmOverloads
        @Synchronized
        fun ds(data: Any?) = logs(data) { tag, txt -> Log.e(tag, txt) }

        @JvmStatic
        @JvmOverloads
        @Synchronized
        fun ws(data: Any?) = logs(data) { tag, txt -> Log.w(tag, txt) }

        @JvmStatic
        @JvmOverloads
        @Synchronized
        fun es(data: Any?) = logs(data) { tag, txt -> Log.e(tag, txt) }

        private inline fun log(data: Any?, tr: Throwable?, lambda: (tag: String, txt: String, tr: Throwable?) -> Unit) {
            if (!CacheUtils.isDebug()) return
            val content = StrUtil.toStr(data) ?: "null"
            lambda(generateTag(), content, tr)
        }

        private inline fun logs(data: Any?, lambda: (tag: String, txt: String) -> Unit) {
            if (!CacheUtils.isDebug()) return
            val tag = generateTag()
            val content = StrUtil.toStr(data) ?: "null"
            var start = 0
            var end = 2000
            while (content.length > start) {
                end = if (content.length > end + 2000) end + 2000 else content.length
                lambda(tag, content.substring(start, end))
                start = end
            }
        }

        /**
         * 外部调用
         *
         * @return
         */
        @JvmOverloads
        fun generateTag(index: Int = 6): String {
            val caller = getCaller(index)
            Thread.currentThread().stackTrace[index]
            var className = caller.className
            className = className.substring(className.lastIndexOf(".") + 1)
            return "$className.${caller.methodName}(L:${caller.lineNumber})"
        }

        private fun getCaller(index: Int = 6): StackTraceElement {
            for (i in 4 until Thread.currentThread().stackTrace.size) {
                val caller = Thread.currentThread().stackTrace[i]
                if (!caller.className.contains("LogUtil")) return caller
            }
            return Thread.currentThread().stackTrace[index]
        }
    }
}